﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Aptea.OpenXmlOffice;
using eCRAM.Dao;
using eCRAM.Model;
using DocumentFormat.OpenXml.Spreadsheet;

namespace eCRAM.Bll
{
    /// <summary>
    /// Classe de génération de l'onglet Save pour les fichiers excel mensuels
    /// </summary>
    public class SaveWorksheetGenerator
    {
        /// <summary>
        /// Nombre de projets autorisés
        /// </summary>
        protected int NbProject { get; private set; }
        /// <summary>
        /// Chemin de destination des exports excel
        /// </summary>
        protected string DestinationFolder { get; private set; }
        /// <summary>
        /// Predicat des projets à exporter
        /// </summary>
        public Func<CramLine, bool> ProjectPredicate { get; set; }
        /// <summary>
        /// Instance du manager Excel
        /// </summary>
        private ExcelManager ExcelManager { get; set; }
        /// <summary>
        /// Cram contenant les données à exporter
        /// </summary>
        public Cram Cram { get; set; }

        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="excelManager"></param>
        public SaveWorksheetGenerator(ExcelManager excelManager)
        {
            ExcelManager = excelManager;
            NbProject = int.Parse(ParameterRepository.GetByEnum(EnumParameter.NbProjetEsportExcel).Value);
            DestinationFolder = ParameterRepository.GetByEnum(EnumParameter.RepertoireExportExcel).Value;
        }

        /// <summary>
        /// Genere le contenu de l'onglet
        /// </summary>
        public virtual void Generate()
        {
            if (!Directory.Exists(DestinationFolder))
            {
                Directory.CreateDirectory(DestinationFolder);
            }

            var workSheet = ExcelManager.AddWorksheet("Save", OrientationValues.Landscape);
            ExcelManager.AddColumnData(workSheet, 1, 1, 5);
            ExcelManager.AddColumnData(workSheet, 2, 2, 5);
            ExcelManager.AddColumnData(workSheet, 3, 3, 50);
            ExcelManager.AddColumnData(workSheet, 4, 4, 200);
            ExcelManager.AddColumnData(workSheet, 5, 5, 200);

            ExcelManager.AddDataToSheet(workSheet, 1, 1, Cram.Year);
            ExcelManager.AddDataToSheet(workSheet, 1, 2, Cram.Month);
            ExcelManager.AddDataToSheet(workSheet, 1, 3, GetProjectsInfo(NbProject, ProjectPredicate));
            ExcelManager.AddDataToSheet(workSheet, 1, 4, GetCramInfo() + GetHolidaysInfo());
            
        }

        /// <summary>
        /// Obtient la chaine de caractéres correspondant aux infos relatives aux congés
        /// </summary>
        /// <returns></returns>
        private string GetHolidaysInfo()
        {
            var tabHolidays = ActivityManager.GetOrderedHolidaysForExcel();

            var sb = new List<string>();

            foreach (var holiday in tabHolidays)
            {
                CramLine line = null;
                if(holiday != null)
                {
                    line = Cram.CramLines.FirstOrDefault(l => l.Activity.Id == holiday.Id);
                }
                if(line != null)
                {
                    sb.Add(GetMonthlyString(line));
                }
                else
                {
                    sb.Add(string.Empty.PadLeft(31, ';'));
                }
            }
            return string.Join("", sb);
        }

        /// <summary>
        /// Obtient la chaine de caractéres correspondant aux infos relatives aux projets
        /// </summary>
        /// <returns></returns>
        private string GetCramInfo()
        {
            var sb = new List<string>();
            foreach (var line in Cram.CramLines.Where(ProjectPredicate).Take(NbProject))
            {
                sb.Add(GetMonthlyString(line));
            }

            while (sb.Count < NbProject)
            {
                sb.Add(string.Empty.PadLeft(31, ';'));
            }

            return string.Join("", sb);
        }

        /// <summary>
        /// Obtient les imputations sur un mois separés par des ;
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        private string GetMonthlyString(CramLine line)
        {
            var sb = new string[31];
            var rates = CramManager.GetMonthRates(Cram, line);
            for (var i = 0; i < 31; i++)
            {
                if (i < rates.Count && rates[i + 1] != 0)
                {
                    sb[i] = rates[i + 1].ToString("0.#");
                }
            }
            return string.Join(";", sb)+";";
        }

        /// <summary>
        /// Obtient une chaine de caractére contenant les libellés des projets
        /// </summary>
        /// <param name="nbElement"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        private string GetProjectsInfo(int nbElement, Func<CramLine, bool> predicate)
        {
            var sb = new List<string>();
            foreach (var line in Cram.CramLines.Where(predicate).Take(nbElement))
            {
                sb.Add(line.Activity.Name);
            }

            sb.Add(string.Empty.PadLeft(nbElement - sb.Count - 1, ';'));

            return string.Join(";", sb);

        }
    }
}
